package com.example.services;

import com.example.draw.LotteryAlgorithmFactory;
import com.example.draw.algorithm.LotteryAlgorithm;
import com.example.exception.BusinessException;
import com.example.mapper.LotteryActivityDao;
import com.example.mapper.LotteryPrizeDao;
import com.example.mapper.LotteryRecordDao;
import com.example.mapper.LotteryUserChanceDao;
import com.example.pojo.LotteryActivity;
import com.example.pojo.LotteryPrize;
import com.example.pojo.LotteryRecord;
import com.example.pojo.LotteryUserChance;
import com.example.vo.LotteryResult;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class LotteryService {
    
    @Autowired
    private LotteryActivityDao activityDao;
    
    @Autowired
    private LotteryPrizeDao prizeDao;
    
    @Autowired
    private LotteryRecordDao recordDao;
    
    @Autowired
    private LotteryUserChanceDao userChanceDao;

    @Autowired
    private LotteryAlgorithmFactory algorithmFactory;
    
    /**
     * 执行抽奖
     */
    public LotteryResult draw(Long userId, Long activityId, String ip) {
        // 1. 验证活动
        LotteryActivity activity = validateActivity(activityId);

        // 2. 验证用户抽奖资格
        validateUserChance(userId, activityId);

        // 3. 获取奖品列表
        List<LotteryPrize> prizes = prizeDao.getByActivityId(activityId);

        // 4. 根据活动配置选择算法
        LotteryAlgorithm algorithm = algorithmFactory.getAlgorithm(activity.getAlgorithmType());

        // 5. 执行抽奖
        LotteryPrize prize = algorithm.draw(prizes);

        // 6. 扣减库存（如果中奖）
        if (prize.getId() != null && !"谢谢参与".equals(prize.getName())) {
            prizeDao.reduceStock(prize.getId(), 1);
        }

        // 7. 记录抽奖结果
        LotteryRecord record = saveRecord(userId, activityId, prize, ip);

        // 8. 更新用户抽奖次数
        updateUserChance(userId, activityId);

        return buildResult(activity, prize, record);
    }
    
    private LotteryActivity validateActivity(Long activityId) {
        LotteryActivity activity = activityDao.getById(activityId);
        if (activity == null) {
            throw new BusinessException("活动不存在");
        }
        
        Date now = new Date();
        if (now.before(activity.getStartTime())) {
            throw new BusinessException("活动未开始");
        }
        
        if (now.after(activity.getEndTime())) {
            throw new BusinessException("活动已结束");
        }
        
        return activity;
    }
    
    private void validateUserChance(Long userId, Long activityId) {
        LotteryUserChance userChance = userChanceDao.getUserChance(userId, activityId);
        if (userChance == null) {
            throw new BusinessException("用户无抽奖资格");
        }
        
        if (userChance.getUsedChance() >= userChance.getTotalChance()) {
            throw new BusinessException("抽奖次数已用完");
        }
        
        // 检查每日限制
        // ...
    }

    private LotteryRecord saveRecord(Long userId, Long activityId, LotteryPrize prize, String ip) {
        LotteryRecord record = new LotteryRecord();
        record.setUserId(userId);
        record.setActivityId(activityId);
        record.setPrizeId(prize.getId());
        record.setPrizeName(prize.getName());
        record.setWinning(!"谢谢参与".equals(prize.getName()));
        record.setIpAddress(ip);
        record.setStatus(0);
        
        recordDao.insert(record);
        return record;
    }
    
    private void updateUserChance(Long userId, Long activityId) {
        userChanceDao.updateUserChance(userId, activityId, 1, new Date());
    }
    
    private LotteryResult buildResult(LotteryActivity activity, LotteryPrize prize, LotteryRecord record) {
        LotteryResult result = new LotteryResult();
        result.setActivityName(activity.getName());
        result.setPrizeName(prize.getName());
        result.setWinning(record.getWinning());
        result.setRecordId(record.getId());
        result.setDrawTime(record.getDrawTime());
        return result;
    }

}
